package com.cloud.salon.client.business.service.impl;

import com.cloud.salon.client.business.feign.MenberFeign;
import com.cloud.salon.client.business.repository.RecordRepository;
import com.cloud.salon.client.business.service.*;
import com.cloud.salon.common.base.constant.PaymentTypeConstant;
import com.cloud.salon.common.base.constant.PreferentialConstant;
import com.cloud.salon.common.base.entity.business.Payment;
import com.cloud.salon.common.base.entity.business.Preference;
import com.cloud.salon.common.base.entity.menber.Account;
import com.cloud.salon.common.base.entity.menber.Staff;
import com.cloud.salon.common.base.util.ValueUtil;
import com.cloud.salon.common.base.vo.business.ItemLineVO;
import com.cloud.salon.common.base.vo.business.PayVO;
import com.cloud.salon.common.base.vo.business.RecordInfoVO;
import com.cloud.salon.common.crud.service.impl.CRUDServiceImpl;
import com.cloud.salon.common.base.constant.RecordStatusConstant;
import com.cloud.salon.common.base.entity.business.Item;
import com.cloud.salon.common.base.response.Res;
import com.cloud.salon.common.base.entity.business.Record;
import com.cloud.salon.common.base.vo.business.PlaceOrderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description 记录Service实现类
 * @Author wolf--LZH
 * @CreateDate 2019/4/10 0010 下午 1:30
 */
@Service
public class RecordServiceImpl extends CRUDServiceImpl<Record, RecordRepository> implements RecordService {

	@Autowired
	private RecordRepository repository;
	@Autowired
	private RecordItemService recordItemService;
	@Autowired
	private ItemService itemService;
	@Autowired
	private PaymentService paymentService;
	@Autowired
	private PreferentialService preferentialService;
	@Autowired
	MenberFeign menberFeign;

	public Res<List<RecordInfoVO>> findAllInfo() {
		Sort sort = new Sort(Sort.Direction.DESC, "date");
		List<Record> records = repository.findAll(sort);
		if (records == null)
			return new Res(-3, "查询错误");

		List<RecordInfoVO> recordInfoVOS = new ArrayList<>();
		for (Record record: records) {
			Res<Staff> staffRes = menberFeign.findStaff(record.getStaffId());
			Res<Account> accountRes = menberFeign.findAccount(record.getAccountId());

			if (staffRes.getStatus() != 0)
				return new Res(-3, "查询错误,请检查订单信息是否出错");

			RecordInfoVO recordInfoVO = null;
			if (accountRes.getStatus() == 0)
				recordInfoVO = new RecordInfoVO(record, accountRes.getData().getNumber(), staffRes.getData().getName());
			else
				recordInfoVO = new RecordInfoVO(record, "非会员顾客", staffRes.getData().getName());

			recordInfoVOS.add(recordInfoVO);
		}

		return new Res(0, "查询成功", recordInfoVOS);
	}

	public Res<Record> placeOrder(PlaceOrderVO placeOrderVO) {
		// 获取会员
		Account account = menberFeign.findAccount(placeOrderVO.getAccountId()).getData();
		// 获取该会员所选的会员优惠
		List<Preference> preferences = null;
		if (account != null) {
			preferences = preferentialService.findByAccountInId(account.getId(), placeOrderVO.getPreferenceIdList()).getData();
			if (preferences == null)
				return new Res(-3, "获取会员优惠失败,请稍后重试");
		}

		// 获取员工
		Staff staff = menberFeign.findStaff(placeOrderVO.getStaffId()).getData();
		if (staff== null)
			return new Res(-3, "请正确输入操作员工的信息");

		// 新建下单记录
		Record record = new Record();
		record.setAccountId(account != null? account.getId(): null);
		record.setStaffId(staff.getId());
		record.setDate(new Date());
		record.setStatus(RecordStatusConstant.UNPAY);

		// 若计算错误则,下单失败
		Res<String> totalRes = calcTotal(preferences, placeOrderVO.getItemIdList(), placeOrderVO.getPreferenceIdList());
		if (totalRes.getStatus() == -1)
			return new Res(-3, totalRes.getMsg());
		// 设置总价
		record.setTotalPrice(ValueUtil.valueOfDouble(totalRes.getData()));

		// 保存进数据库
		Record temp = repository.save(record);

		// 设置优惠id列表
		List<Integer> preferenceIdList = null;
		if (account == null) {
			preferenceIdList = new ArrayList<>();
			for (int i = 0; i < placeOrderVO.getItemIdList().size(); i++)
				preferenceIdList.add(0);
		}
		else
			preferenceIdList = placeOrderVO.getPreferenceIdList();
		// 设置项目关联
		Res res = recordItemService.setRecordItems(temp.getId(), placeOrderVO.getItemIdList(), preferenceIdList);

		// 修改具体优惠信息
		for (Preference preference: preferences) {
			if (preference.getTimes() != null && preference.getTimes() > 0) {
				Res<Integer> preferenceRes = preferentialService.setTimes(preference.getId(), -1);
				if (preferenceRes.getStatus() != 0)
					return new Res(-3, preferenceRes.getMsg());
			}
		}

		if(res.getStatus() == 0)
			return new Res(0, "下单成功", temp);
		return  new Res(-3, "下单失败,请稍后再试");
	}

	public Res<String> calcTotal(PlaceOrderVO placeOrderVO) {
		// 通过会员id尝试获取会员
		Account account = menberFeign.findAccount(placeOrderVO.getAccountId()).getData();

		// 获取该会员的所有会员优惠
		List<Preference> preferences = null;
		if (account != null)
			preferences = preferentialService.findByAccount(account.getId()).getData();

		return calcTotal(preferences, placeOrderVO.getItemIdList(), placeOrderVO.getPreferenceIdList());
	}

	public Res pay(PayVO payVO) {
		// 容错
		if (!payVO.correct())
			return new Res(-3, "参数错误,请确保参数正确");

		// 查看是否含有该交易记录
		Res<Record> recordRes = this.findById(payVO.getRecordId());
		if (recordRes.getData() == null)
			return new Res(-3, "无此记录");

		// 查看记录状态
		Record record = recordRes.getData();
		if (!RecordStatusConstant.UNPAY.equals(record.getStatus()) && !RecordStatusConstant.UNPAY_CLEAR.equals(record.getStatus()))
			return new Res(-3, "该记录已支付或已取消,无法进行支付");

		// 获取该记录下所有支付
		Res<List<Payment>> paymentsRes = paymentService.findByRecord(payVO.getRecordId());
		if (paymentsRes.getStatus() == -3)
			return paymentsRes;
		List<Payment> payments = paymentsRes.getData();

		// 计算总已支付金额
		Double sum = 0.0;
		for (Payment payment: payments)
			sum += payment.getPayAmount();

		// 创建支付实体
		Payment payment = new Payment(record.getId(), new Date(), payVO.getPayAmount(), payVO.getType());
		Account account = null;

		// 按支付类型进行支付处理
		boolean clear = false;
		if (PaymentTypeConstant.CASH.equals(payVO.getType())) {
			// 计算找零
			sum += payVO.getPayAmount();
			Double change = sum - record.getTotalPrice();
			// 判断是否付清
			clear = change >= 0;
			// 设置支付的找零
			payment.setChange(clear? change: 0.0);
		}
		else if (PaymentTypeConstant.VIP_BALANCE.equals(payVO.getType())) {
			// 获取支付的会员
			account = menberFeign.findAccount(payVO.getAccountId()).getData();
			// 若无该会员,则为当前订单记录的会员
			if (account == null) {
				account = menberFeign.findAccount(record.getAccountId()).getData();
				if (account == null)
					return new Res(-3, "无此会员,请重新确定");
			}
			// 计算会员余额支付
			Double balance = account.getBalance();
			Double cost = record.getTotalPrice() - sum;
			clear = payVO.getPayAmount() >= cost;
			cost = clear? cost: payVO.getPayAmount();
			// 判断余额是否充足
			if (balance <= 0 || balance < cost)
				return new Res(-3, "该会员余额为0,无法支付");
			payment.setPayAmount(cost);
		}
		else
			return new Res(-3, "暂不支持此类型的支付");

		// 保存该支付
		if (paymentService.save(payment).getStatus() == -3)
			return new Res(-3, "支付失败,请稍后再试");
		// 更新记录
		if (clear) {
			record.setStatus(RecordStatusConstant.PAID);
			repository.save(record);
		}
		else if (RecordStatusConstant.UNPAY.equals(record.getStatus())) {
			record.setStatus(RecordStatusConstant.UNPAY_CLEAR);
			repository.save(record);
		}
		// 更新账户余额
		if (account != null) {
			Account accountDelta = new Account();
			accountDelta.setId(account.getId());
			accountDelta.setBalance(-payment.getPayAmount());
			Res<Integer> accountRes = menberFeign.setAccountBalance(accountDelta);
			if (accountRes.getStatus() != 0)
				return new Res(-3, "会员余额更新错误");
		}

		return new Res(0, "支付成功", ValueUtil.valueOf(2, payment.getChange()));
	}

	private Res<String> calcTotal(List<Preference> preferences, List<Integer> itemIdList, List<Integer> preferenceIdList) {
		// 初始化
		Double total = 0.0;

		// 参数检查
		int length = itemIdList.size();
		if (preferences != null && length != preferenceIdList.size())
			return new Res(-3, "参数错误");

//		// 检查是否为会员
//		List<Preference> preferences = null;
//		if (account != null) {
//			// 若是,则获取该会员的所有会员优惠
//			preferences = preferentialService.findByAccount(account.getId()).getData();
//			if (preferences == null)
//				return new Res(-3, "计算错误,请稍后重试");
//		}

		// 获取具体项目
		List<Item> items = itemService.findByIdList(itemIdList).getData();
		if (items == null)
			return new Res(-3, "计算错误,获取具体项目失败");

		// 开始计算
		int index = 0;
		for (Item item: items) {
			// 非会员价格计算
			if (preferences == null)
				total += item.getPrice();
				// 会员价格计算
			else {
				// 若当前优惠id为0,则说明不使用具体权益
				if (preferenceIdList.get(index) == 0) {
					total += item.getPrice();
					continue;
				}
				// 通过优惠id获取具体的优惠
				Preference preference = null;
				for (Preference temp: preferences) {
					if (temp.getId().equals(preferenceIdList.get(index))) {
						// 判断优惠剩余次数是否大于零
						if (temp.getTimes() == null || temp.getTimes() > 0)
							preference = temp;
						break;
					}
				}
				// 判断优惠类型并计算
				if (preference == null)
					total += item.getPrice();
				else if (PreferentialConstant.DISCOUNT.equals(preference.getType()))
					total += item.getPrice() * preference.getDiscount();
				else if (PreferentialConstant.VOUCHER.equals(preference.getType())) {
					total += item.getPrice() - preference.getVoucher() >= 0? item.getPrice() - preference.getVoucher(): 0;
				}
			}
			index++;
		}
		return new Res(0, "计算成功", ValueUtil.valueOf(2, total));
	}
}
